home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 May / EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso / earcd / mus / play / mikmod.lzh / mikmod / load_xm.c < prev    next >
C/C++ Source or Header  |  1997-01-28  |  15KB  |  598 lines

  1. /*
  2.  
  3. Name:
  4. LOAD_XM.C
  5.  
  6. Description:
  7. Fasttracker (XM) module loader
  8.  
  9. Portability:
  10. All systems - all compilers (hopefully)
  11.  
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. /* #include <malloc.h> */
  18. #include "mikmod.h"
  19.  
  20. /**************************************************************************
  21. **************************************************************************/
  22.  
  23.  
  24. typedef struct XMHEADER{
  25.     char  id[17];                   /* ID text: 'Extended module: ' */
  26.     char  songname[21];             /* Module name, padded with zeroes and 0x1a at the end */
  27.     char  trackername[20];  /* Tracker name */
  28.     UWORD version;                  /* (word) Version number, hi-byte major and low-byte minor */
  29.     ULONG headersize;               /* Header size */
  30.     UWORD songlength;               /* (word) Song length (in patten order table) */
  31.     UWORD restart;                  /* (word) Restart position */
  32.     UWORD numchn;                   /* (word) Number of channels (2,4,6,8,10,...,32) */
  33.     UWORD numpat;                   /* (word) Number of patterns (max 256) */
  34.     UWORD numins;                   /* (word) Number of instruments (max 128) */
  35.     UWORD flags;                    /* (word) Flags: bit 0: 0 = Amiga frequency table (see below) 1 = Linear frequency table */
  36.     UWORD tempo;                    /* (word) Default tempo */
  37.     UWORD bpm;                              /* (word) Default BPM */
  38.     UBYTE orders[256];              /* (byte) Pattern order table */
  39. } XMHEADER;
  40.  
  41.  
  42. typedef struct XMINSTHEADER{
  43.     ULONG size;                             /* (dword) Instrument size */
  44.     char  name[22];                 /* (char) Instrument name */
  45.     UBYTE type;                             /* (byte) Instrument type (always 0) */
  46.     UWORD numsmp;                   /* (word) Number of samples in instrument */
  47.     ULONG ssize;                    /* */
  48. } XMINSTHEADER;
  49.  
  50.  
  51. typedef struct XMPATCHHEADER{
  52.     UBYTE what[96];         /* (byte) Sample number for all notes */
  53.     UBYTE volenv[48];       /* (byte) Points for volume envelope */
  54.     UBYTE panenv[48];       /* (byte) Points for panning envelope */
  55.     UBYTE volpts;           /* (byte) Number of volume points */
  56.     UBYTE panpts;           /* (byte) Number of panning points */
  57.     UBYTE volsus;           /* (byte) Volume sustain point */
  58.     UBYTE volbeg;           /* (byte) Volume loop start point */
  59.     UBYTE volend;           /* (byte) Volume loop end point */
  60.     UBYTE pansus;           /* (byte) Panning sustain point */
  61.     UBYTE panbeg;           /* (byte) Panning loop start point */
  62.     UBYTE panend;           /* (byte) Panning loop end point */
  63.     UBYTE volflg;           /* (byte) Volume type: bit 0: On; 1: Sustain; 2: Loop */
  64.     UBYTE panflg;           /* (byte) Panning type: bit 0: On; 1: Sustain; 2: Loop */
  65.     UBYTE vibflg;           /* (byte) Vibrato type */
  66.     UBYTE vibsweep;         /* (byte) Vibrato sweep */
  67.     UBYTE vibdepth;         /* (byte) Vibrato depth */
  68.     UBYTE vibrate;          /* (byte) Vibrato rate */
  69.     UWORD volfade;          /* (word) Volume fadeout */
  70.     UWORD reserved[11];     /* (word) Reserved */
  71. } XMPATCHHEADER;
  72.  
  73.  
  74. typedef struct XMWAVHEADER{
  75.     ULONG length;           /* (dword) Sample length */
  76.     ULONG loopstart;        /* (dword) Sample loop start */
  77.     ULONG looplength;       /* (dword) Sample loop length */
  78.     UBYTE volume;           /* (byte) Volume */
  79.     SBYTE finetune;          /* (byte) Finetune (signed byte -128..+127) */
  80.     UBYTE type;                     /* (byte) Type: Bit 0-1: 0 = No loop, 1 = Forward loop, */
  81. /*                                        2 = Ping-pong loop; */
  82. /*                                        4: 16-bit sampledata */
  83.     UBYTE panning;          /* (byte) Panning (0-255) */
  84.     SBYTE  relnote;          /* (byte) Relative note number (signed byte) */
  85.     UBYTE reserved;         /* (byte) Reserved */
  86.     char  samplename[22];   /* (char) Sample name */
  87. } XMWAVHEADER;
  88.  
  89.  
  90. typedef struct XMPATHEADER{
  91.     ULONG size;                             /* (dword) Pattern header length */
  92.     UBYTE packing;                  /* (byte) Packing type (always 0) */
  93.     UWORD numrows;                  /* (word) Number of rows in pattern (1..256) */
  94.     UWORD packsize;                 /* (word) Packed patterndata size */
  95. } XMPATHEADER;
  96.  
  97. typedef struct MTMNOTE{
  98.     UBYTE a,b,c;
  99. } MTMNOTE;
  100.  
  101.  
  102. typedef struct XMNOTE{
  103.     UBYTE note,ins,vol,eff,dat;
  104. }XMNOTE;
  105.  
  106. XMNOTE *xmpat;
  107.  
  108. /**************************************************************************
  109. **************************************************************************/
  110.  
  111.  
  112.  
  113. static XMHEADER *mh;
  114.  
  115. char XM_Version[]="XM";
  116.  
  117.  
  118.  
  119. BOOL XM_Test(void)
  120. {
  121.     char id[17];
  122.     if(!fread(id,17,1,modfp)) return 0;
  123.     if(!memcmp(id,"Extended Module: ",17)) return 1;
  124.     return 0;
  125. }
  126.  
  127.  
  128. BOOL XM_Init(void)
  129. {
  130.     mh=NULL;
  131.     if(!(mh=MyCalloc(1,sizeof(XMHEADER)))) return 0;
  132.     return 1;
  133. }
  134.  
  135.  
  136. void XM_Cleanup(void)
  137. {
  138.     if(mh!=NULL) free(mh);
  139. }
  140.  
  141.  
  142. void XM_ReadNote(XMNOTE *n)
  143. {
  144.     UBYTE cmp;
  145.     memset(n,0,sizeof(XMNOTE));
  146.  
  147.     cmp=fgetc(modfp);
  148.  
  149.     if(cmp&0x80){
  150.         if(cmp&1) n->note=fgetc(modfp);
  151.         if(cmp&2) n->ins=fgetc(modfp);
  152.         if(cmp&4) n->vol=fgetc(modfp);
  153.         if(cmp&8) n->eff=fgetc(modfp);
  154.         if(cmp&16) n->dat=fgetc(modfp);
  155.     }
  156.     else{
  157.         n->note=cmp;
  158.         n->ins=fgetc(modfp);
  159.         n->vol=fgetc(modfp);
  160.         n->eff=fgetc(modfp);
  161.         n->dat=fgetc(modfp);
  162.     }
  163. }
  164.  
  165.  
  166. UBYTE *XM_Convert(XMNOTE *xmtrack,UWORD rows)
  167. {
  168.     int t;
  169.     UBYTE note,ins,vol,eff,dat;
  170.  
  171.     UniReset();
  172.  
  173.     for(t=0;t<rows;t++){
  174.  
  175.         note=xmtrack->note;
  176.         ins=xmtrack->ins;
  177.         vol=xmtrack->vol;
  178.         eff=xmtrack->eff;
  179.         dat=xmtrack->dat;
  180.  
  181.         if(note!=0){
  182.             UniNote(note-1);
  183.         }
  184.  
  185.         if(ins!=0){
  186.             UniInstrument(ins-1);
  187.         }
  188.  
  189. /*              printf("Vol:%d\n",vol); */
  190.  
  191.         switch(vol>>4){
  192.  
  193.             case 0x6:                    /* volslide down */
  194.                 if(vol&0xf){
  195.                     UniWrite(UNI_XMEFFECTA);
  196.                     UniWrite(vol&0xf);
  197.                 }
  198.                 break;
  199.  
  200.             case 0x7:                    /* volslide up */
  201.                 if(vol&0xf){
  202.                     UniWrite(UNI_XMEFFECTA);
  203.                     UniWrite(vol<<4);
  204.                 }
  205.                 break;
  206.  
  207.             /* volume-row fine volume slide is compatible with protracker
  208.                EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
  209.                opposed to 'take the last sliding value'.
  210.             */
  211.  
  212.             case 0x8:                        /* finevol down */
  213.                 UniPTEffect(0xe,0xb0 | (vol&0xf));
  214.                 break;
  215.  
  216.             case 0x9:                       /* finevol up */
  217.                 UniPTEffect(0xe,0xa0 | (vol&0xf));
  218.                 break;
  219.  
  220.             case 0xa:                       /* set vibrato speed */
  221.                 UniPTEffect(0x4,vol<<4);
  222.                 break;
  223.  
  224.             case 0xb:                       /* vibrato */
  225.                 UniPTEffect(0x4,vol&0xf);
  226.                 break;
  227.  
  228.             case 0xc:                       /* set panning */
  229.                 UniPTEffect(0x8,vol<<4);
  230.                 break;
  231.  
  232.             case 0xd:                       /* panning slide left */
  233.                 /* only slide when data nibble not zero: */
  234.  
  235.                 if(vol&0xf){
  236.                     UniWrite(UNI_XMEFFECTP);
  237.                     UniWrite(vol&0xf);
  238.                 }
  239.                 break;
  240.  
  241.             case 0xe:                       /* panning slide right */
  242.                 /* only slide when data nibble not zero: */
  243.  
  244.                 if(vol&0xf){
  245.                     UniWrite(UNI_XMEFFECTP);
  246.                     UniWrite(vol<<4);
  247.                 }
  248.                 break;
  249.  
  250.             case 0xf:                       /* tone porta */
  251.                 UniPTEffect(0x3,vol<<4);
  252.                 break;
  253.  
  254.             default:
  255.                 if(vol>=0x10 && vol<=0x50){
  256.                     UniPTEffect(0xc,vol-0x10);
  257.                 }
  258.         }
  259.  
  260. /*              if(eff>0xf) printf("Effect %d",eff); */
  261.  
  262.         switch(eff){
  263.  
  264.             case 'G'-55:                    /* G - set global volume */
  265.                 break;
  266.  
  267.             case 'H'-55:                    /* H - global volume slide */
  268.                 break;
  269.  
  270.             case 'K'-55:                    /* K - keyoff */
  271.                 UniNote(96);
  272.                 break;
  273.  
  274.             case 'L'-55:                    /* L - set envelope position */
  275.                 break;
  276.  
  277.             case 'P'-55:                    /* P - panning slide */
  278.                 UniWrite(UNI_XMEFFECTP);
  279.                 UniWrite(dat);
  280.                 break;
  281.  
  282.             case 'R'-55:                    /* R - multi retrig note */
  283.                 UniWrite(UNI_S3MEFFECTQ);
  284.                 UniWrite(dat);
  285.                 break;
  286.  
  287.             case 'T'-55:
  288.                 UniPTEffect(0x6,dat);
  289.                 break;
  290.  
  291.             case 'X'-55:
  292.                 if((dat>>4)==1){                /* X1 extra fine porta up */
  293.  
  294.  
  295.                 }
  296.                 else{                                   /* X2 extra fine porta down */
  297.  
  298.                 }
  299.                 break;
  300.  
  301.             default:
  302.                 if(eff==0xa){
  303.                     UniWrite(UNI_XMEFFECTA);
  304.                     UniWrite(dat);
  305.                 }
  306.                 else if(eff<=0xf) UniPTEffect(eff,dat);
  307.                 break;
  308.         }
  309.  
  310.         UniNewline();
  311.         xmtrack++;
  312.     }
  313.     return UniDup();
  314. }
  315.  
  316.  
  317.  
  318. BOOL XM_Load(void)
  319. {
  320.     INSTRUMENT *d;
  321.     SAMPLE *q;
  322.     int t,u,v,p,numtrk;
  323.     long next;
  324.  
  325.     /* try to read module header */
  326.  
  327.     _mm_read_str(mh->id,17,modfp);
  328.     _mm_read_str(mh->songname,21,modfp);
  329.     _mm_read_str(mh->trackername,20,modfp);
  330.     mh->version        =_mm_read_I_UWORD(modfp);
  331.     mh->headersize    =_mm_read_I_ULONG(modfp);
  332.     mh->songlength    =_mm_read_I_UWORD(modfp);
  333.     mh->restart        =_mm_read_I_UWORD(modfp);
  334.     mh->numchn        =_mm_read_I_UWORD(modfp);
  335.     mh->numpat        =_mm_read_I_UWORD(modfp);
  336.     mh->numins        =_mm_read_I_UWORD(modfp);
  337.     mh->flags        =_mm_read_I_UWORD(modfp);
  338.     mh->tempo        =_mm_read_I_UWORD(modfp);
  339.     mh->bpm            =_mm_read_I_UWORD(modfp);
  340.     _mm_read_UBYTES(mh->orders,256,modfp);
  341.  
  342.     if(feof(modfp)){
  343.         myerr = ERROR_LOADING_HEADER;
  344.         return 0;
  345.     }
  346.  
  347.     /* set module variables */
  348.  
  349.     of.initspeed=mh->tempo;
  350.     of.inittempo=mh->bpm;
  351.     of.modtype=DupStr(mh->trackername,20);
  352.     of.numchn=mh->numchn;
  353.     of.numpat=mh->numpat;
  354.     of.numtrk=(UWORD)of.numpat*of.numchn;   /* get number of channels */
  355.     of.songname=DupStr(mh->songname,20);    /* make a cstr of songname */
  356.     of.numpos=mh->songlength;                       /* copy the songlength */
  357.     of.reppos=mh->restart;
  358.     of.numins=mh->numins;
  359.     of.flags|=UF_XMPERIODS;
  360.     if(mh->flags&1) of.flags|=UF_LINEAR;
  361.  
  362.     memcpy(of.positions,mh->orders,256);
  363.  
  364.     of.numpat=0;
  365.     for(t=0;t<of.numpos;t++){
  366.         if(of.positions[t]>of.numpat) of.numpat=of.positions[t];
  367.     }
  368.     of.numpat++;
  369.  
  370. /*    printf("Modtype :%s\n",of.modtype);
  371.     printf("Version :%x\n",mh->version);
  372.     printf("Song    :%s\n",of.songname);
  373.     printf("Speed   :%d,%d\n",of.initspeed,of.inittempo);
  374.     printf("Channels:%d\n",of.numchn);
  375.     printf("Numins  :%d\n",mh->numins);
  376. */
  377.     if(!AllocTracks()) return 0;
  378.     if(!AllocPatterns()) return 0;
  379.  
  380.     numtrk=0;
  381.     for(t=0;t<mh->numpat;t++){
  382.         XMPATHEADER ph;
  383.  
  384. /*        printf("Reading pattern %d\n",t); */
  385.  
  386.         ph.size        =_mm_read_I_ULONG(modfp);
  387.         ph.packing    =_mm_read_UBYTE(modfp);
  388.         ph.numrows    =_mm_read_I_UWORD(modfp);
  389.         ph.packsize    =_mm_read_I_UWORD(modfp);
  390.  
  391. /*        printf("headln:  %ld\n",ph.size); */
  392. /*        printf("numrows: %d\n",ph.numrows); */
  393. /*        printf("packsize:%d\n",ph.packsize); */
  394.  
  395.         of.pattrows[t]=ph.numrows;
  396.  
  397.         /*
  398.             Gr8.. when packsize is 0, don't try to load a pattern.. it's empty.
  399.             This bug was discovered thanks to Khyron's module..
  400.         */
  401.  
  402.         if(!(xmpat=MyCalloc(ph.numrows*of.numchn,sizeof(XMNOTE)))) return 0;
  403.  
  404.         if(ph.packsize>0){
  405.             for(u=0;u<ph.numrows;u++){
  406.                 for(v=0;v<of.numchn;v++){
  407.                     XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
  408.                 }
  409.             }
  410.         }
  411.  
  412.         for(v=0;v<of.numchn;v++){
  413.             of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
  414.         }
  415.  
  416.         free(xmpat);
  417.     }
  418.  
  419.     if(!AllocInstruments()) return 0;
  420.  
  421.     d=of.instruments;
  422.  
  423.     for(t=0;t<of.numins;t++){
  424.         XMINSTHEADER ih;
  425.  
  426.         /* read instrument header */
  427.  
  428.         ih.size        =_mm_read_I_ULONG(modfp);
  429.         _mm_read_str (ih.name, 22, modfp);
  430.         ih.type        =_mm_read_UBYTE(modfp);
  431.         ih.numsmp    =_mm_read_I_UWORD(modfp);
  432.         ih.ssize    =_mm_read_I_ULONG(modfp);
  433.  
  434. /*      printf("Size: %ld\n",ih.size);
  435.         printf("Name:     %22.22s\n",ih.name);
  436.         printf("Samples:%d\n",ih.numsmp);
  437.         printf("sampleheadersize:%ld\n",ih.ssize);
  438. */
  439.         d->insname=DupStr(ih.name,22);
  440.         d->numsmp=ih.numsmp;
  441.  
  442.         if(!AllocSamples(d)) return 0;
  443.  
  444.         if(ih.numsmp>0){
  445.             XMPATCHHEADER pth;
  446.             XMWAVHEADER wh;
  447.  
  448.             _mm_read_UBYTES (pth.what, 96, modfp);
  449.             _mm_read_UBYTES (pth.volenv, 48, modfp);
  450.             _mm_read_UBYTES (pth.panenv, 48, modfp);
  451.             pth.volpts        =_mm_read_UBYTE(modfp);
  452.             pth.panpts        =_mm_read_UBYTE(modfp);
  453.             pth.volsus        =_mm_read_UBYTE(modfp);
  454.             pth.volbeg        =_mm_read_UBYTE(modfp);
  455.             pth.volend        =_mm_read_UBYTE(modfp);
  456.             pth.pansus        =_mm_read_UBYTE(modfp);
  457.             pth.panbeg        =_mm_read_UBYTE(modfp);
  458.             pth.panend        =_mm_read_UBYTE(modfp);
  459.             pth.volflg        =_mm_read_UBYTE(modfp);
  460.             pth.panflg        =_mm_read_UBYTE(modfp);
  461.             pth.vibflg        =_mm_read_UBYTE(modfp);
  462.             pth.vibsweep    =_mm_read_UBYTE(modfp);
  463.             pth.vibdepth    =_mm_read_UBYTE(modfp);
  464.             pth.vibrate        =_mm_read_UBYTE(modfp);
  465.             pth.volfade        =_mm_read_I_UWORD(modfp);
  466.             _mm_read_I_UWORDS(pth.reserved, 11, modfp);
  467.  
  468.             memcpy(d->samplenumber,pth.what,96);
  469.  
  470.             d->volfade=pth.volfade;
  471.  
  472. /*            printf("Volfade %x\n",d->volfade); */
  473.  
  474.             memcpy(d->volenv,pth.volenv,24);
  475.             d->volflg=pth.volflg;
  476.             d->volsus=pth.volsus;
  477.             d->volbeg=pth.volbeg;
  478.             d->volend=pth.volend;
  479.             d->volpts=pth.volpts;
  480.  
  481. /*            printf("volume points    : %d\n"
  482.                    "volflg            : %d\n"
  483.                    "volbeg            : %d\n"
  484.                    "volend            : %d\n"
  485.                    "volsus            : %d\n",
  486.                    d->volpts,
  487.                    d->volflg,
  488.                    d->volbeg,
  489.                    d->volend,
  490.                    d->volsus);
  491. */
  492.             /* scale volume envelope: */
  493.  
  494.             for(p=0;p<12;p++){
  495.                 d->volenv[p].val<<=2;
  496. /*                printf("%d,%d,",d->volenv[p].pos,d->volenv[p].val); */
  497.             }
  498.  
  499.             memcpy(d->panenv,pth.panenv,24);
  500.             d->panflg=pth.panflg;
  501.             d->pansus=pth.pansus;
  502.             d->panbeg=pth.panbeg;
  503.             d->panend=pth.panend;
  504.             d->panpts=pth.panpts;
  505.  
  506. /*                      printf("Panning points    : %d\n"
  507.                    "panflg            : %d\n"
  508.                    "panbeg            : %d\n"
  509.                    "panend            : %d\n"
  510.                    "pansus            : %d\n",
  511.                    d->panpts,
  512.                    d->panflg,
  513.                    d->panbeg,
  514.                    d->panend,
  515.                    d->pansus);
  516. */
  517.             /* scale panning envelope: */
  518.  
  519.             for(p=0;p<12;p++){
  520.                 d->panenv[p].val<<=2;
  521. /*                printf("%d,%d,",d->panenv[p].pos,d->panenv[p].val); */
  522.             }
  523.  
  524. /*                      for(u=0;u<256;u++){ */
  525. /*                              printf("%2.2x ",fgetc(modfp)); */
  526. /*                      } */
  527.  
  528.             next=0;
  529.  
  530.             for(u=0;u<ih.numsmp;u++){
  531.                 q=&d->samples[u];
  532.  
  533.                 wh.length        =_mm_read_I_ULONG (modfp);
  534.                 wh.loopstart    =_mm_read_I_ULONG (modfp);
  535.                 wh.looplength    =_mm_read_I_ULONG (modfp);
  536.                 wh.volume        =_mm_read_UBYTE (modfp);
  537.                 wh.finetune        =_mm_read_SBYTE (modfp);
  538.                 wh.type            =_mm_read_UBYTE (modfp);
  539.                 wh.panning        =_mm_read_UBYTE (modfp);
  540.                 wh.relnote        =_mm_read_SBYTE (modfp);
  541.                 wh.reserved        =_mm_read_UBYTE (modfp);
  542.                 _mm_read_str(wh.samplename, 22, modfp);
  543.  
  544. /*              printf("wav %d:%22.22s\n",u,wh.samplename); */
  545.  
  546.                 q->samplename   =DupStr(wh.samplename,22);
  547.                 q->length       =wh.length;
  548.                 q->loopstart    =wh.loopstart;
  549.                 q->loopend      =wh.loopstart+wh.looplength;
  550.                 q->volume       =wh.volume;
  551.                 q->c2spd        =wh.finetune+128;
  552.                 q->transpose    =wh.relnote;
  553.                 q->panning      =wh.panning;
  554.                 q->seekpos        =next;
  555.  
  556.                 if(wh.type&0x10){
  557.                     q->length>>=1;
  558.                     q->loopstart>>=1;
  559.                     q->loopend>>=1;
  560.                 }
  561.  
  562.                 next+=wh.length;
  563.  
  564. /*                              printf("Type %u\n",wh.type); */
  565. /*                printf("Trans %d\n",wh.relnote); */
  566.  
  567.                 q->flags|=SF_OWNPAN;
  568.                 if(wh.type&0x3) q->flags|=SF_LOOP;
  569.                 if(wh.type&0x2) q->flags|=SF_BIDI;
  570.  
  571.                 if(wh.type&0x10) q->flags|=SF_16BITS;
  572.                 q->flags|=SF_DELTA;
  573.                 q->flags|=SF_SIGNED;
  574.             }
  575.  
  576.             for(u=0;u<ih.numsmp;u++) d->samples[u].seekpos+=_mm_ftell(modfp);
  577.  
  578.             _mm_fseek(modfp,next,SEEK_CUR);
  579.         }
  580.  
  581.         d++;
  582.     }
  583.  
  584.  
  585.     return 1;
  586. }
  587.  
  588.  
  589. LOADER load_xm={
  590.     NULL,
  591.     "XM",
  592.     "Portable XM loader v0.4 - for your ears only / MikMak",
  593.     XM_Init,
  594.     XM_Test,
  595.     XM_Load,
  596.     XM_Cleanup
  597. };
  598.